<?php
/**
 * Created by PhpStorm.
 * User: chenangel
 * Date: 2017/7/29
 * Time: 上午9:16
 */

namespace common\helpers;

use common\rest\statics\ResponseDatum;
use cza\base\vendor\widgets\plupload\ChunkUploader;
use yii\db\Exception;
use yii\helpers\FileHelper;
use yii\web\Response;
use yii\web\UploadedFile;
use yii\base\Component;

class ImageUploadHelper extends Component
{

    public $maxSize = '10';
    public $tempPath = '@api/runtime/plupload';
    protected $_organizer;
    public $dirMode = 0775;

    public function init()
    {
        parent::init();
        $this->_organizer = \Yii::$app->czaHelper->folderOrganizer;
        \Yii::$app->response->format = Response::FORMAT_JSON;

        $this->tempPath = \Yii::getAlias($this->tempPath);
        if (!is_dir($this->tempPath)) {
            FileHelper::createDirectory($this->tempPath, $this->dirMode, true);
        }
    }

    /**
     * @param $imageFile UploadedFile
     * @param $entityModel
     * @param $attachmentClass
     * @param $entityClass
     * @param $entityAttribute
     * @param bool $isOnly
     * @return array|null
     * @throws \Exception
     * @throws \yii\base\Exception
     * @throws \yii\base\InvalidConfigException
     */
    public function uploadImageFile($imageFile, $entityModel, $attachmentClass,
                                    $entityClass, $entityAttribute, $extras = [], $isOnly = false)
    {
        try {
            if ($isOnly) {
                $attributor = [
                    'entity_class' => $entityClass,
                    'entity_id' => $entityModel->id,
                    'entity_attribute' => $entityAttribute,
                ];
                $attachementModel = $attachmentClass::findAll($attributor);
                if (!empty($attachementModel)) {
                    foreach ($attachementModel as $item) {
                        if ($item) {
                            $item->beforeDelete();
                            $item->delete();
                        }
                    }
                }
            }
            $chunkPath = $this->getUnusedPath($this->tempPath . DIRECTORY_SEPARATOR . $imageFile->name);
            $isUploadComplete = ChunkUploader::process($imageFile, $chunkPath);

            if ($isUploadComplete) {
                $fileHash = md5(microtime(true) . $chunkPath);
                $fileType = $imageFile->getExtension();
                $newFileName = "{$fileHash}.{$fileType}";
                $entityModel = $entityModel;
                if (is_null($entityModel)) {
                    throw new \yii\base\Exception("entity model(id:{$entityModel->id}) not found!");
                }
                $fileDirPath = $this->_organizer->getFullUploadStoreDir($fileHash, $entityModel);
                $newFilePath = $fileDirPath . DIRECTORY_SEPARATOR . $newFileName;

                if (!copy($chunkPath, $newFilePath)) {
                    throw new \Exception("Cannot copy file! {$chunkPath}  to {$newFilePath}");
                }
                $attachment = new $attachmentClass;
                $attachment->loadDefaultValues();
                $attachment->setAttributes([
                    'name' => $entityModel->id . time() . rand(1, 20),
                    'entity_id' => $entityModel->id,
                    'entity_class' => $entityClass,
                    'entity_attribute' => $entityAttribute,
                    'hash' => $fileHash,
                    'size' => filesize($chunkPath),
                    'content' => isset($extras['content']) ? $extras['content'] : "",
                    'extension' => $fileType,
                    'mime_type' => FileHelper::getMimeType($chunkPath),
                    'logic_path' => $this->_organizer->getUploadLogicPath($fileHash, $entityModel),
                ]);
                if ($attachment->save()) {
                    @\unlink($chunkPath);
                    \Yii::info('$attachment->errors', 'debug');
                    \Yii::info($attachment->errors, 'debug');
                    return [
                        'filename' => $newFilePath,
                    ];
                } else {
                    \Yii::info('$attachment->null', 'debug');
                    return null;
                }
            }

        } catch (Exception $e) {
            \Yii::info('$uploadImage', 'debug');
            \Yii::info($e, 'debug');
        }


    }

    /**
     * @param $image_base64 图片base64
     * @param $entityId  图片对应模型ID
     * @param $attachementClass   图片附件的模型类
     * @param $entityClass   图片对应模型类
     * @param $entityAttribute
     * @param bool $isOnly
     * @return array|null
     * @throws \Exception
     * @throws \yii\base\Exception
     * @throws \yii\base\InvalidConfigException
     */
    public function uploadImage($image_base64, $entityId, $attachementClass, $entityClass, $entityAttribute, $extras = [], $isOnly = false)
    {

        try {
            if ($isOnly) {
                $attributor = [
                    'entity_class' => $entityClass,
                    'entity_id' => $entityId,
                    'entity_attribute' => $entityAttribute,
                ];
                $attachementModel = $attachementClass::findAll($attributor);
                if (!empty($attachementModel)) {
                    foreach ($attachementModel as $item) {
                        if ($item) {
                            $item->beforeDelete();
                            $item->delete();
                        }
                    }
                }
            }
            $uploadedFile = $this->makeTempFile($image_base64);
            $filePath = $this->getUnusedPath($this->tempPath . DIRECTORY_SEPARATOR . $uploadedFile->name);
            \Yii::info('$filePath-' . $filePath, 'debug');
            $isUploadComplete = ChunkUploader::process($uploadedFile, $filePath);
            if ($isUploadComplete) {
                $fileHash = md5(microtime(true) . $filePath);
                $fileType = isset($image['name']) ? strtolower(substr(stristr($image['name'], '.'), 1)) : strtolower(pathinfo($filePath, PATHINFO_EXTENSION));
                $newFileName = "{$fileHash}.{$fileType}";
                $entityModel = $entityClass::findOne(['id' => $entityId]);
                if (is_null($entityModel)) {
                    throw new \yii\base\Exception("entity model(id:{$entityId}) not found!");
                }

                $fileDirPath = $this->_organizer->getFullUploadStoreDir($fileHash, $entityModel);
                $newFilePath = $fileDirPath . DIRECTORY_SEPARATOR . $newFileName;

                if (!copy($filePath, $newFilePath)) {
                    throw new \Exception("Cannot copy file! {$filePath}  to {$newFilePath}");
                }
                $attachement = new $attachementClass;
                $attachement->loadDefaultValues();
                $attachement->setAttributes([
                    //                'name' => pathinfo($filePath, PATHINFO_FILENAME),
                    //                'type' => $attachement->type,
                    'name' => $entityId . time() . rand(1, 20),
                    'entity_id' => $entityId,
                    'entity_class' => $entityClass,
                    'entity_attribute' => $entityAttribute,
                    'hash' => $fileHash,
                    'size' => filesize($filePath),
                    'content' => isset($extras['content']) ? $extras['content'] : "",
                    'extension' => $fileType,
                    'mime_type' => FileHelper::getMimeType($filePath),
                    'logic_path' => $this->_organizer->getUploadLogicPath($fileHash, $entityModel),
                ]);
                \Yii::info('&--' . $attachement->entity_id, 'debug');

                if ($attachement->save()) {
                    @\unlink($filePath);
                    \Yii::info('$attachement->errors', 'debug');
                    \Yii::info($attachement->errors, 'debug');
                    return [
                        'filename' => $newFilePath,
                    ];
                } else {
                    \Yii::info('$attachement->null', 'debug');
                    return null;
                }
            }

        } catch (Exception $e) {
            \Yii::info('$uploadImage', 'debug');
            \Yii::info($e, 'debug');
        }
    }

    public function makeTempFile($attribute)
    {
        //        if (!$this->hasFileValue($attribute)) {
        //            return false;
        //        }
        $tempName = tempnam(sys_get_temp_dir(), 'ub_');
        if (preg_match('/^data:([\w\/]+);base64/i', $attribute, $matches)) {
            list($type, $data) = explode(';', $attribute);
            list(, $data) = explode(',', $attribute);
            $data = base64_decode($data);

            $name = uniqid('ub_');

            if (!empty($matches[1])) {
                $extensions = FileHelper::getExtensionsByMimeType($matches[1]);
                $name .= '.' . end($extensions);
            }

            if (!file_put_contents($tempName, $data)) {
                return false;
            }
        } else {
            return false;
        }

        return new UploadedFile([
            'name' => $name,
            'type' => $type,
            'tempName' => $tempName
        ]);
    }

    /**
     * Returns an unused file path by adding a filename suffix if necessary.
     * @param string $path
     * @return string
     */
    protected function getUnusedPath($path)
    {
        $newPath = $path;
        $info = pathinfo($path);
        $suffix = 1;

        while (file_exists($newPath)) {
            $newPath = $info['dirname'] . DIRECTORY_SEPARATOR . "{$info['filename']}_{$suffix}";
            if (isset($info['extension'])) {
                $newPath .= ".{$info['extension']}";
            }
            $suffix++;
        }

        return $newPath;
    }

}